/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.inria.openmath.omapi;

/**
 *
 * @author Mr.Sam
 */
public class OMException extends RuntimeException {

    /** This is not a legal exception error code */
    public final static short OME_UNKNOWN = 0;

    /** Something unsupected went wrong */
    public final static short OME_INTERNAL = 1;

    /** This exception is a wrapper (it holds another one) */
    public final static short OME_WRAPPING = 2;

    /** This is the vanilla exception */
    public final static short OME_GENERIC = 3;

    /** A node that was required has not been found */
    public final static short OME_NODE_NOT_FOUND = 4;

    /** A syntax error occured during a parsing process */
    public final static short OME_SYNTAX = 5;

    /** A conversion to int was unsuccessful due to
     * an overflow */
    public final static short OME_INT_OVERFLOW = 6;

    /** A request has been made that breaks the
     * hierarchy rules of OpenMath trees
     * eg: looking for children of a node that can't have
     * children.
     */
    public final static short OME_HIERARCHY_REQUEST = 7;

    /** When requested base is not legal. <p> eg: in the Float.setPreferedBase()
     */
    public final static short OME_UNLEGAL_BASE = 8;

    /** Mark the end of object during parsing
     */
    public final static short OME_END_OBJECT = 9;

    /** Some more detailed human informative message */
    private String message;

    /** The specific error code that refines the plain OMException. */
    private short errorCode;

    /** Wrapped exception (if any) */
    private Exception exception;

    /**
     * Creates a new OMException.
     *
     * @param message The error message.
     */
    public OMException (String message) {
        super();
        this.message = message;
        this.errorCode = OME_GENERIC;
        this.exception = null;
    }

    /**
     * Creates a new OMException wrapping an existing exception.
     *
     * <p>The existing exception will be embedded in the new
     * one, and its message will become the default message for
     * the OMException.</p>
     *
     * @param e The exception to be wrapped in a OMException.
     */
    public OMException (Exception e) {
        super();
        this.message = null;
        this.errorCode = OME_WRAPPING;
        this.exception = e;
    }

    /**
     * Creates a new OMException from an existing exception.
     *
     * <p>The existing exception will be embedded in the new
     * one, but the new exception will have its own message.</p>
     *
     * @param message The detail message.
     * @param e The exception to be wrapped in a OMException.
     */
    public OMException (String message, Exception e) {
        super();
        this.message = message;
        this.errorCode = OME_WRAPPING;
        this.exception = e;
    }

    /**
     * Creates a new OMException with a message and an specific error code.
     *
     * @param message The detail message.
     * @param errorCode The specific error code.
     */
    public OMException (String message, short errorCode) {
        super();
        this.message = message;
        this.errorCode = errorCode;
        this.exception = null;
    }

    /**
     * Returns a detail message for this exception.
     *
     * <p>If there is a embedded exception, and if the OMException
     * has no detail message of its own, this method will return
     * the detail message from the embedded exception.</p>
     *
     * @return The error message.
     */
    public String getMessage() {
        if (message == null && exception != null) {
            return exception.getMessage();
        } else {
            return this.message;
        }
    }

    /**
     * Returns the embedded exception, if any.
     *
     * @return The embedded exception, or null if there is none.
     */
    public Exception getException() {
        return exception;
    }

    /**
     * Returns the specific error code of this exception.
     *
     * @return The specific error code of this exception.
     */
    public short getErrorCode() {
        return errorCode;
    }

    /**
     * Converts this exception to a string.
     *
     * @return A string version of this exception.
     */
    public String toString() {
        if (exception == null) {
            if (message != null)
                return message + " (code " + getErrorCode() + ")";
            else
                return getMessage() + " (code " + getErrorCode() + ")";
        } else {
            if (message != null)
                return getMessage() + "\n" + exception;
            else
                return exception.getMessage();
        }
    }

}
